package com.luoke.service.request.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.luoke.connect.GameWebSocketClient;
import com.luoke.constants.ModuleTypeConstant;
import com.luoke.constants.StatusConstant;
import com.luoke.constants.SubmoduleTypeConstant;
import com.luoke.context.UserContext;
import com.luoke.handler.request.BattleRequestHandler;
import com.luoke.pojo.dto.BagDTO;
import com.luoke.pojo.dto.BattleRoundDTO;
import com.luoke.pojo.dto.InitiateBattleDTO;
import com.luoke.pojo.entity.BattlePet;
import com.luoke.pojo.entity.Skill;
import com.luoke.result.Result;
import com.luoke.service.request.BattleRequestService;
import com.luoke.manage.threadmanage.FutureManager;

import java.util.Scanner;
import java.util.concurrent.CompletableFuture;

/**
 * 战斗请求服务层
 */
public class BattleRequestServiceImpl implements BattleRequestService {


    /**
     * 向用户发起对战
     * @param gameWebSocketClient 使用该对象与服务端通信
     * @param scanner 输入流
     */
    @Override
    public void startPvpBattle(GameWebSocketClient gameWebSocketClient, Scanner scanner) {
        //进入pvp模块，首先先发请求给服务端，并在响应处理中展示当前在线玩家
        Result result = new Result();
        result.setModuleName(ModuleTypeConstant.BATTLE);
        result.setCommand(SubmoduleTypeConstant.SHOW_WAIT_FOR_USER);

//        System.out.println(UserContext.getCurrentUser());
        //注册一个CompletableFuture
        FutureManager.registerFuture(UserContext.getCurrentUser(), new CompletableFuture<>());
        gameWebSocketClient.send(JSONUtil.toJsonStr(result));

        // FutureManager.getFuture(UserContext.getCurrentUser()).join();   无法完成，因为异步的原因，complete()方法会在join()方法之前执行，导致程序一直被阻塞

        // 使用 thenAccept 注册回调，当任务完成时触发 ，，， 即当触发complete()方法的时候，才会执行的回调方法
        FutureManager.getFuture(UserContext.getCurrentUser()).thenAccept(p -> {
            System.out.println();
            System.out.println("请输入要对战的玩家名(输入back返回菜单): ");
            String battleName = scanner.nextLine();
            if (battleName.equals("back")) {
                new BattleRequestHandler().showGameMenu(gameWebSocketClient); //当输入back时返回游戏菜单
            } else {
                System.out.println("正在向 " + battleName + " 发起对战请求");
                System.out.println("请等待对手同意.....");
                //向服务端发送请求
                Result<InitiateBattleDTO> request = new Result<>();
                request.setModuleName(ModuleTypeConstant.BATTLE);
                request.setCommand(SubmoduleTypeConstant.INITIATE_BATTLE_REQUEST);

                request.setData(new InitiateBattleDTO(UserContext.getCurrentUser(), battleName,null,false));
                gameWebSocketClient.send(JSONUtil.toJsonStr(request));
                //请求之后进入等待
                FutureManager.registerFuture(UserContext.getCurrentUser(), new CompletableFuture<Object>());
                FutureManager.getFuture(UserContext.getCurrentUser()).thenAccept(isSuccess->{
                    //响应之后进行回调
                    if(isSuccess.equals(StatusConstant.SUCCESS)){
                        //对方同意对战
                        System.out.println("玩家 " + battleName + " 同意了你的对战请求");
                        System.out.println("开始进入对战");
                        //进入对战逻辑


                    } else if (isSuccess.equals(StatusConstant.FAIL)) {
                        System.out.println("玩家 " + battleName + " 拒绝了你的对战请求");
                        //被拒绝之后要返回游戏菜单
                        new BattleRequestHandler().showGameMenu(gameWebSocketClient);
                    }else if(isSuccess.equals(StatusConstant.NO_WAIT)){
                        System.out.println("玩家不在对战等待区或玩家不在线..");
                        new BattleRequestHandler().showGameMenu(gameWebSocketClient);
                    }
                });
            }
        });
    }

    /**
     * 发送请求，使服务器标志该用户为等待状态
     * @param gameWebSocketClient 使用该对象与服务端通信
     * @param scanner 输入流
     */
    @Override
    public void userToWait(GameWebSocketClient gameWebSocketClient, Scanner scanner) {

        Result request = new Result();
        request.setModuleName(ModuleTypeConstant.BATTLE);
        request.setCommand(SubmoduleTypeConstant.WAIT_FOR_USER);
        request.setData(UserContext.getCurrentUser());
        gameWebSocketClient.send(JSONUtil.toJsonStr(request)); //发送请求

        System.out.println();
        System.out.println("您已经进入等待状态，请等待玩家的邀请....");


        FutureManager.registerFuture(UserContext.getCurrentUser(), new CompletableFuture<>());
        FutureManager.getFuture(UserContext.getCurrentUser()).thenAccept(user-> {
            InitiateBattleDTO data = (InitiateBattleDTO)user;

            //等待服务器的消息
            System.out.println("玩家 " + data.getInitiatorName() + " 向你发送了对战邀请");
            System.out.println("请输入(accept/reject)同意或拒绝该邀请: ");
            String result = scanner.nextLine();
            Result response;
            if (result.equals(StatusConstant.ACCEPT)) {
                //同意
                System.out.println("您同意了对战邀请，正在进入战斗状态...");
                //向服务端发送同意的请求
                response = new Result();
                response.setModuleName(ModuleTypeConstant.BATTLE);
                response.setCommand(SubmoduleTypeConstant.ACCEPT_BATTLE_INVITATION);



                if (data.getIsMatch()){  //判断是否是匹配
                    response.setData(new InitiateBattleDTO(data.getInitiatorName(), UserContext.getCurrentUser(), "accept", true));

                }else {
                    response.setData(new InitiateBattleDTO(data.getInitiatorName(), UserContext.getCurrentUser(), "accept",false));

                }


                gameWebSocketClient.send(JSONUtil.toJsonStr(response));
                //TODO 进入战斗程序





            } else if (result.equals(StatusConstant.REJECT)) {
                //拒绝
                System.out.println("您拒绝了对战邀请，正在返回游戏菜单");
                //向服务端发送拒绝的请求
                response = new Result();
                response.setModuleName(ModuleTypeConstant.BATTLE);
                response.setCommand(SubmoduleTypeConstant.ACCEPT_BATTLE_INVITATION);
                if (data.getIsMatch()){
                    response.setData(new InitiateBattleDTO(data.getInitiatorName(), UserContext.getCurrentUser(), "reject",true));

                }else {
                    response.setData(new InitiateBattleDTO(data.getInitiatorName(), UserContext.getCurrentUser(), "reject",false));

                }

                gameWebSocketClient.send(JSONUtil.toJsonStr(response));
                new BattleRequestHandler().showGameMenu(gameWebSocketClient);
            }



        });


    }

    /**
     * 向服务端发起匹配对战请求
     * 其实就是向服务端中在等待区的玩家中进行随机匹配
     * @param gameWebSocketClient 使用该对象与服务端通信
     * @param scanner 输入流
     */
    @Override
    public void matchBattle(GameWebSocketClient gameWebSocketClient, Scanner scanner) {

        System.out.println("正在进行随机匹配，请稍等...");

        //向服务端发送请求
        Result request = new Result();
        request.setModuleName(ModuleTypeConstant.BATTLE);
        request.setCommand(SubmoduleTypeConstant.MATCH_BATTLE);
        InitiateBattleDTO initiateBattleDTO = new InitiateBattleDTO(UserContext.getCurrentUser(), null, null,true);
        request.setData(initiateBattleDTO);
        gameWebSocketClient.send(JSONUtil.toJsonStr(request));
        FutureManager.registerFuture(UserContext.getCurrentUser(), new CompletableFuture<>());//注册异步处理器
        //回调
        FutureManager.getFuture(UserContext.getCurrentUser()).thenAccept(user -> {

            if (user==null){
                System.out.println("等待区玩家人数不足，匹配失败");
                new BattleRequestHandler().showGameMenu(gameWebSocketClient);
            }else {
                System.out.println("你与 "+user+" 匹配成功了,正在发送邀请....");
                System.out.println("请等待对方响应");
                //发送邀请由服务端完成  这里不需要再次请求
                FutureManager.registerFuture(UserContext.getCurrentUser(), new CompletableFuture<>());//注册异步处理器
                FutureManager.getFuture(UserContext.getCurrentUser()).thenAccept(result->{
                    //如果接受了对战
                    if (result!=null){
                        System.out.println("邀请已经被接受");
                        System.out.println("对战开始........");
                    }else{
                        System.out.println("匹配失败，对方拒绝了你的邀请");
                        //转跳回游戏菜单
                        new BattleRequestHandler().showGameMenu(gameWebSocketClient);
                    }
                });
            }
        });
    }

    /**
     * 对每个回合发起的技能，背包中的物品，宠物进行提交处理
     * @param gameWebSocketClient
     * @param other
     */
    @Override
    public void doRound(GameWebSocketClient gameWebSocketClient, String other) {
        Result<String> request = new Result<>();
        request.setModuleName(ModuleTypeConstant.BATTLE_ROUND);
        request.setCommand(SubmoduleTypeConstant.OPPONENT_ROUND_COMPLETED);
        request.setMessage(UserContext.getCurrentUser()+"完成操作");
        request.setFromUser(other);
        gameWebSocketClient.send(JSONUtil.toJsonStr(request));
    }

    /**
     * 使用背包的请求
     *
     * @param gameWebSocketClient
     * @param toUser
     * @param bagDTO
     */
    @Override
    public void useBag(GameWebSocketClient gameWebSocketClient, String toUser, BagDTO bagDTO) {
        Result<BagDTO> request = new Result<>();
        request.setModuleName(ModuleTypeConstant.BATTLE_ROUND);
        request.setCommand(SubmoduleTypeConstant.OPPONENT_ROUND_COMPLETED);
        request.setMessage(UserContext.getCurrentUser()+"完成操作，使用了: "+ bagDTO.getGoodsName()+", "+bagDTO.getDescription()+"了"+bagDTO.getValue()+"点");
        request.setData(bagDTO);
//        request.setFromUser(UserContext.getCurrentUser());
        request.setFromUser(toUser);
        request.setToUser(UserContext.getCurrentUser());
        gameWebSocketClient.send(JSONUtil.toJsonStr(request));
    }

    /**
     * 切换宠物的请求
     * @param gameWebSocketClient
     * @param toUser
     * @param battlePet
     */
    @Override
    public void changePet(GameWebSocketClient gameWebSocketClient, String toUser, BattlePet battlePet) {
        Result<BattlePet> request = new Result<>();
        request.setModuleName(ModuleTypeConstant.BATTLE_ROUND);
        request.setCommand(SubmoduleTypeConstant.OPPONENT_ROUND_COMPLETED);
        request.setMessage(UserContext.getCurrentUser()+"完成操作,切换了宠物: "+battlePet.getPetName());
        request.setData(battlePet);
        request.setFromUser(toUser);
        gameWebSocketClient.send(JSONUtil.toJsonStr(request));
    }

    /**
     * 使用技能的请求
     *
     * @param gameWebSocketClient
     * @param skill
     */
    @Override
    public void useSkill(GameWebSocketClient gameWebSocketClient, Skill skill) {
        Result<Skill> request = new Result<>();
        request.setModuleName(ModuleTypeConstant.BATTLE_ROUND);
        request.setCommand(SubmoduleTypeConstant.OPPONENT_ROUND_COMPLETED);
        request.setMessage(StrUtil.format("{}【{}】使用{}技能"
                ,UserContext.getCurrentUser()
                ,UserContext.getCurrentPet().getPetName()
                ,skill.getName()));
        request.setData(skill);
        request.setFromUser(UserContext.getCurrentUser());
        gameWebSocketClient.send(JSONUtil.toJsonStr(request));
    }


}
